package com.daJiao.service.impl;

import cn.hutool.extra.pinyin.PinyinUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.daJiao.domain.PageParam;
import com.daJiao.constants.Constants;
import com.daJiao.domain.ResourceInfo;
import com.daJiao.domain.RoleBindResource;
import com.daJiao.domain.RoleBindUser;
import com.daJiao.domain.SecurityUserDetails;
import com.daJiao.entity.SysRole;
import com.daJiao.entity.SysRoleMenu;
import com.daJiao.entity.SysUserRole;
import com.daJiao.enums.DeleteFlagEnums;
import com.daJiao.exception.BusinessException;
import com.daJiao.mapper.SysRoleMapper;
import com.daJiao.service.SysRoleMenuService;
import com.daJiao.service.SysRoleService;
import com.daJiao.service.SysUserRoleService;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    @Resource
    private SysRoleMapper sysRoleMapper;

    @Resource
    private SysUserRoleService sysUserRoleService;

    @Resource
    private SysRoleMenuService sysRoleMenuService;

    @Override
    public int saveRole(SysRole role) {
        SysRole sysRole = sysRoleMapper.selectOne(new QueryWrapper<SysRole>().lambda().eq(SysRole::getDelFlag, DeleteFlagEnums.NORMAL.getStatus()).eq(SysRole::getRoleName,role.getRoleName()));
        if(Objects.nonNull(sysRole)){
            throw new BusinessException("该角色已经存在，不能重复新增");
        }
        role.setRoleCode(PinyinUtil.getPinyin(role.getRoleName()));
        return sysRoleMapper.insert(role);
    }

    @Override
    public int updateRole(SysRole role) {
        SysRole sysRole = sysRoleMapper.selectById(role.getId());
        if(Objects.isNull(sysRole)){
            throw new BusinessException("不合法的id");
        }
        role.setRoleCode(PinyinUtil.getPinyin(role.getRoleName()));
        role.setUpdateTime(LocalDateTime.now());
        return sysRoleMapper.updateById(role);
    }

    @Override
    public int delete(String id, SecurityUserDetails securityUser) {
        SysRole sysRole = sysRoleMapper.selectById(id);
        if(Objects.isNull(sysRole)){
            throw new BusinessException("不合法的id");
        }
        sysRole.setUpdater(securityUser.getRealName());
        sysRole.setUpdateBy(securityUser.getUserId());
        sysRole.setDelFlag(DeleteFlagEnums.DELETE.getStatus());
        sysRole.setUpdateTime(LocalDateTime.now());
        return sysRoleMapper.updateById(sysRole);
    }

    @Override
    public Page<SysRole> listPage(PageParam<SysRole> param) {
        return sysRoleMapper.listPage(new Page(param.getPageNum(), param.getPageSize()),param.getParam());
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void roleBindResource(RoleBindResource roleBindResource, SecurityUserDetails securityUser) {
        SysRole sysRole = sysRoleMapper.selectById(roleBindResource.getRoleId());
        if(Objects.isNull(sysRole)){
            throw new BusinessException("角色信息不存在");
        }

        // 删除角色和菜单的绑定关系
        sysRoleMenuService.batchDeleteByRoleId(roleBindResource.getRoleId());

        if(CollectionUtils.isNotEmpty(roleBindResource.getResourceIds())){
            List<SysRoleMenu> roleMenus = Lists.newArrayList();
            for (ResourceInfo resourceInfo : roleBindResource.getResourceIds().stream().filter(f -> Constants.MENU_TYPE.equals(f.getType())).collect(Collectors.toList())) {
                SysRoleMenu roleMenu = new SysRoleMenu();
                roleMenu.setRoleId(roleBindResource.getRoleId());
                roleMenu.setMenuId(resourceInfo.getResourceId());
                roleMenus.add(roleMenu);
            }
            sysRoleMenuService.saveBatch(roleMenus);
        }
    }

    @Override
    public List<String> getBindResourceByRoleId(String roleId) {
        SysRole sysRole = sysRoleMapper.selectById(roleId);
        if(Objects.isNull(sysRole)){
            throw new BusinessException("角色信息不存在");
        }

        // 查询该角色所绑定的所有菜单信息
        List<SysRoleMenu> roleMenus = sysRoleMenuService.list(new QueryWrapper<SysRoleMenu>().lambda().eq(SysRoleMenu::getRoleId, DeleteFlagEnums.NORMAL.getStatus()));

        // TODO 权限信息以后要做的话再返回
        return roleMenus.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void roleBindUser(RoleBindUser roleBindUser, SecurityUserDetails securityUser) {
        SysRole sysRole = sysRoleMapper.selectById(roleBindUser.getRoleId());
        if(Objects.isNull(sysRole)){
            throw new BusinessException("角色信息不存在");
        }

        // 删除原来的角色用户关系
        sysUserRoleService.batchDeleteByRoleId(roleBindUser.getRoleId());

        // 报错新的用户角色关系
        if(CollectionUtils.isNotEmpty(roleBindUser.getUserIds())){
            List<SysUserRole> userRoles = Lists.newArrayList();
            for (String userId : roleBindUser.getUserIds()) {
                SysUserRole userRole = new SysUserRole();
                userRole.setRoleId(roleBindUser.getRoleId());
                userRole.setUserId(userId);
                userRoles.add(userRole);
            }
            sysUserRoleService.saveBatch(userRoles);
        }

    }

    @Override
    public List<String> getBindUserByRoleId(String roleId) {
        List<SysUserRole> sysUserRoles = sysUserRoleService.list(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getRoleId, roleId));
        return sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());
    }
}
